<?php
/**
 * RedXenon Framework
 * 
 * LICENSE
 * 
 * This source file is subject to the New BSD license that is bundled
 * with this package in the file LICENSE.txt
 * A copy of this license can be found in the world-wide-web at this URL:
 * http://www.redxenon.com/license/new-bsd-license.txt

 * RedXenon Date (RXDate.php)
 * Manages the common Date functionalities
 * 
 * @category RedXenon
 * @package RedXenon_Date
 * @copyright Copyright (c) 2011 Red Xenon (http://www.redxenon.com)
 * @version $Id: RXDate.php 1.0 2011-04-30 $ 
 */
class RXDate {
	
	/**
	 * Represents the date value in epoch unix time format
	 * @var Integer
	 */
	private $unixTime;
	
	/**
	 * Year
	 * @var Integer
	 */
	private $year;
	/**
	 * Month
	 * @var Integer
	 */
	private $month;
	
	/**
	 * Day
	 * @var Integer
	 */
	private $day;
	
	/**
	 * Hour
	 * @var Integer
	 */
	private $hour;
	
	/**
	 * Minute
	 * @var Integer
	 */
	private $minute;
	
	/**
	 * Second
	 * @var Integer
	 */
	private $second;
	
	/**
	 * Language code, e.g. English = "en"
	 * @var String
	 */
	private $language;
	
	/**
	 * Represents the difference of hours between the current date
	 * and the GMT +00:00 time zone 
	 * @var Integer
	 */
	private $gmtDiff;
	
	function __construct($year = 0, $month = 0, $day = 0, 
											$hour = 0, $minute = 0, $second = 0, $gmtDiff = 0, $language = null) {
		$this->year = $year;
		$this->month = $month;
		$this->day = $day;
		$this->hour = $hour;
		$this->minute = $minute;
		$this->second = $second;
		$this->gmtDiff = $gmtDiff;
		self::updateUnixTime();
		
		$this->language = $language;
	}
	
	/**
	 * Updates the epoch unix time with the current date and time values
	 */
	public function updateUnixTime(){
		$this->unixTime = gmmktime($this->hour, $this->minute, $this->second, $this->month, $this->day, $this->year);
	}
	
	/**
	 * Updates the date values with the current epoch unix time
	 */
	public function updateDateValues(){
		if($this->unixTime){
			$this->year = date("Y", $this->unixTime);
			$this->month = date("n", $this->unixTime);
			$this->day = date("j", $this->unixTime);
			$this->hour = date("G", $this->unixTime);
			$this->minute = date("i", $this->unixTime);
			$this->second = date("s", $this->unixTime);
		}
	}
	
	/**
	 * Compares the current object with another	 
	 * @param RXDate $date Another date
	 * @return 	1 if current object date is greater than $date
	 * @return -1 if $date is grater than the current object date
	 * @return 0 if both dates are same
	 */
	public function compare(RXDate $date){
		if($this->unixTime > $date->getUnixTime()){
			return 1;
		}else if($this->unixTime < $date->getUnixTime()){
			return -1;
		}else{
			return 0;
		}
	}
	
	/**
	 * Returns a string with the current format
	 * under the PHP date function parameters
	 * and translates it in case of language set up
	 * @param $format String
	 * @param $language String of two characters that describes the language to 
	 * 				translate the date
	 */
	public function getDate($format = NULL, $language = NULL){
		
		if(is_null($format)){
			$format = DATE_RFC822;
		}
		
		$this->language = $language;
		
		if((preg_match('/O/', $format) || preg_match('/P/', $format)) && $this->gmtDiff != 0){
			if($this->gmtDiff < 0){
				$addition = " -";
			}else{
				$addition = " +";
			}
			
			if($this->gmtDiff < 10 && $this->gmtDiff > -10){
				$addition .= "0";
			}
			
			$addition .= $this->gmtDiff;
			
			if(preg_match('/P/', $format)){
				$addition .= ":";
			}
			
			$addition .= "00";
		}
		$textDate = date($format, $this->unixTime+32400).$addition;
		
		$this->language = strtolower($this->language);
		if(is_null($this->language) || $this->language != "en"){
			require_once ("RXDateLanguages.php");
			$dateTranslator = new RXDateLanguages();
			
			if($dateTranslator->getDateTranslation($this->language)){
				
				/* Short textual day name */
				if(preg_match('/D/', $format) 
					&& $dateTranslator->getShortDayTranslation($this->language)){
					$textDate = str_replace(	$dateTranslator->getShortDayTranslation("en"), 
											$dateTranslator->getShortDayTranslation($this->language), 
											$textDate);
				}
				
				/* Long textual day name */
				if(preg_match('/l/', $format) 
					&& $dateTranslator->getDayTranslation($this->language)){
					$textDate = str_replace(	$dateTranslator->getDayTranslation('en'), 
											$dateTranslator->getDayTranslation($this->language), 
											$textDate);
				}
				
				/* Short textual month name */
				if(preg_match('/M/', $format) 
					&& $dateTranslator->getShortMonthTranslation($this->language)){
					$textDate = str_replace(	$dateTranslator->getShortMonthTranslation("en"), 
											$dateTranslator->getShortMonthTranslation($this->language), 
											$textDate);
				}
				
				/* Short textual day name */
				if(preg_match('/F/', $format) 
					&& $dateTranslator->getMonthTranslation($this->language)){
					$textDate = str_replace(	$dateTranslator->getMonthTranslation("en"), 
											$dateTranslator->getMonthTranslation($this->language), 
											$textDate);
				}
			}
		}
		
		return $textDate;
	}
	
	/**
	 * Sets the current date object to time() values
	 */
	public function now(){
		$this->unixTime = time();
		self::updateDateValues();
	}
	
	/**
	 * Creates a date from a formatted text
	 * @param String $format
	 * @param String $date text expression
	 */
	public function createFromFormat($format, $date){
		$format = preg_replace("/dd/i", "d", $format);
		$format = preg_replace("/mm/i", "m", $format);
		$format = preg_replace("/yyyy/i", "Y", $format);
		$format = preg_replace("/yy/i", "y", $format);
		$dateTime = DateTime::createFromFormat($format, $date);
		if($dateTime){
			$this->unixTime = $dateTime->getTimeStamp();
			self::updateDateValues();
		}else{
			$this->unixTime = FALSE;
			throw new Exception("Invalid Format (createFromFormat) \"".$format."\"");
		}
	}
	
	/**
	 * Returns the Sql value for the following types
	 * DATETIME 		'YYYY-MM-DD HH:MM:SS'
	 * DATE 				'YYYY-MM-DD'
	 * TIMESTAMP 	'YYYY-MM-DD HH:MM:SS'
	 * TIME 				'HH:MM:SS'
	 * @param $type of conversion
	 * @return String Sql value
	 */
	public function getSqlDate($type){
		switch($type){
			case "DATETIME": 
			case "TIMESTAMP":	return date("Y-m-d H:i:s",	$this->unixTime);
			case "DATE":				return date("Y-m-d",			$this->unixTime);
			case "TIME":				return date("H:i:s",				$this->unixTime);
			default:						throw new Exception("Invalid Format Type (getSqlDate) \"".$type."\"");
												return NULL;
		}
	}
	
	/**
	 * Sets the value of the date from the Sql value for the following types
	 * DATETIME 		'YYYY-MM-DD HH:MM:SS'
	 * DATE 				'YYYY-MM-DD'
	 * TIMESTAMP 	'YYYY-MM-DD HH:MM:SS'
	 * TIME 				'HH:MM:SS'
	 * @param $type of conversion
	 * @param String $date sql expression
	 */
	public function setSqlDate($type, $value){
		switch($type){
			case "DATETIME":
			case "TIMESTAMP":	self::createFromFormat("Y-m-d H:i:s", $value);	break;
			case "DATE":				self::createFromFormat("Y-m-d", $value);			break;
			case "TIME":				self::createFromFormat("H:i:s", $value); 			break;
			default:						throw new Exception("Invalid Format Type (setSqlDate) \"".$type."\"");
		}
	}

	/**
	 * @return Integer value of the $unixTime in epoch unix time format
	 */
	public function getUnixTime() {		
		return $this->unixTime;
	}

	/**
	 * @return The $year value
	 */
	public function getYear() {
		return $this->year;
	}

	/**
	 * @return The $month value
	 */
	public function getMonth() {
		return $this->month;
	}

	/**
	 * @return The $day value
	 */
	public function getDay() {
		return $this->day;
	}

	/**
	 * @return The $hour value
	 */
	public function getHour() {
		return $this->hour;
	}

	/**
	 * @return The $minute value
	 */
	public function getMinute() {
		return $this->minute;
	}

	/**
	 * @return The $second value
	 */
	public function getSecond() {
		return $this->second;
	}

	/**
	 * @return The $gmtDiff value
	 */
	public function getGmtDiff() {
		return $this->gmtDiff;
	}
	
	/**
	 * @return The $language code
	 */
	public function getLanguage(){
		return $this->language;
	}

	/**
	 * @param $unixTime Value of a date in epoch unix time format
	 */
	public function setUnixTime($unixTime) {
		$this->unixTime = $unixTime;
		self::updateDateValues();
	}

	/**
	 * @param $year Integer value
	 */
	public function setYear($year) {
		$this->year = $year;
		self::updateUnixTime();
	}

	/**
	 * @param $month Integer value
	 */
	public function setMonth($month) {
		$this->month = $month;
		self::updateUnixTime();
	}

	/**
	 * @param $day Integer value
	 */
	public function setDay($day) {
		$this->day = $day;
		self::updateUnixTime();
	}

	/**
	 * @param $hour Integer value
	 */
	public function setHour($hour) {
		$this->hour = $hour;
		self::updateUnixTime();
	}

	/**
	 * @param $minute Integer value
	 */
	public function setMinute($minute) {
		$this->minute = $minute;
		self::updateUnixTime();
	}

	/**
	 * @param $second Integer value
	 */
	public function setSecond($second) {
		$this->second = $second;
		self::updateUnixTime();
	}

	/**
	 * @param $gmtDiff Integer value
	 */
	public function setGmtDiff($gmtDiff) {
		$this->gmtDiff = $gmtDiff;
	}
	
	/**
	 * @param $languageCode String value
	 */
	public function setLanguage($languageCode){
		$this->language = $languageCode;
	}
}

?>